package com.tcoiss.webservice.apiServer;

import com.tcoiss.common.core.enums.ErroEnums;
import com.tcoiss.common.core.exception.CustomException;
import com.tcoiss.common.core.utils.DateUtils;
import com.tcoiss.webservice.apiServer.xstream.XStream;
import com.tcoiss.webservice.apiServer.xstream.mapper.MapperContext;
import com.tcoiss.webservice.utils.Base64Utils;
import com.tcoiss.webservice.utils.DomUtils;
import java.io.ByteArrayInputStream;
import java.net.ConnectException;
import java.util.HashMap;
import java.util.Map;

import org.apache.axis.AxisFault;
import org.apache.axis.Message;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;


public class SoapInvoker extends Invoker {
    private static XStream xstream = XStream.instance();
    private static Service service = new Service();

    private static final Logger log = LoggerFactory.getLogger(SoapInvoker.class);

    @Override
    public Map<String,Object> invoke(HttpAPIServer httpAPIServer, InvokeContext context) throws Exception {
        context.setEndpoint(endpoint);
        context.setRequestTime(DateUtils.getTime());
        if (subRequestTemplate != null){
            String subReqString = generateSubRequestString(context);
            String base64String = Base64Utils.encode(subReqString);
            Map<String, Object> subReqMap = new HashMap<>();
            subReqMap.put("data",base64String);
            context.setParameters(subReqMap);
        }
        String reqString = generateRequestString(context);
        context.setRequestString(reqString);
        ByteArrayInputStream stream = new ByteArrayInputStream(reqString.trim()
                .getBytes("UTF-8"));
        SOAPEnvelope req = null;
        req = new SOAPEnvelope(stream);
        context.setRequestSOAP(req);
        SOAPEnvelope rsp;
        Call call = new Call(service);
        call.setTargetEndpointAddress(endpoint);

        //.net编写的服务端接口需要多传一个SOAPActionURI参数才能正常调用
        //统一修改为在globalVars中存入soapAction的值
        //setSoapAction(context.getOperationCode(), call);
        if (!StringUtils.isEmpty(MapUtils.getString(globalVars, "soapAction"))) {
            call.setSOAPActionURI(MapUtils.getString(globalVars, "soapAction"));
        }

        if (timeout != null)
            call.setTimeout(new Integer(timeout.intValue() * 1000));
        log.info("resp==>"+req);
        try {
            rsp = call.invoke(req);
        } catch (AxisFault fault) {
            if (fault.detail instanceof ConnectException) {
               /* throw new ApiException("8001",null, "无法连接到操作["
                        + context.getOperationCode() + "]所请求的服务地址");*/
                throw new CustomException(ErroEnums.APIERRO.getCode(),new Object[]{}, ErroEnums.APIERRO.getInfo() + "无法连接到操作["
                        + context.getOperationCode() + "]所请求的服务地址");
            }
            if (fault.detail == null) {
                /*throw new ApiException("8999",null,fault.getFaultString());*/
                throw new CustomException(ErroEnums.APIERRO.getCode(),new Object[]{},
                        ErroEnums.APIERRO.getInfo() + fault.getFaultString());
            }
            context.setFailure(fault.dumpToString());
            if (!transformFault) {
                throw fault;
            }
            Message msg = call.getResponseMessage();
            if (msg != null && msg.getSOAPEnvelope() != null) {
                rsp = msg.getSOAPEnvelope();
            } else {
                //throw new ApiException("8002",null, fault.getFaultString());
                throw new CustomException(ErroEnums.APIERRO.getCode(),new Object[]{},
                        ErroEnums.APIERRO.getInfo() + fault.getFaultString());
            }
        } finally {
            try {
                stream.close();
            } catch (Exception e) {
            }
            context.setResponseTime(DateUtils.getTime());
        }
        Document resultDoc = rsp.getAsDocument();
        context.setResponseSOAP(rsp);
        String resultStr = DomUtils.DocumentToString(resultDoc);
        context.setResponseString(resultStr);
        log.debug("\n\nreqString=" + reqString + "\n\nresultStr="
                + resultStr);
        Map<String,Object> result = new HashMap<>();
        try {
            result = (Map) new XStream().fromXML(resultStr, new MapperContext());
            context.setResultString(result.toString());
        } catch (Exception e) {
            /*throw new ApiException("9003",null, "根据反馈的业务报文转为目标格式["
                    + context.getOperationCode() + "]时出错.");*/
            throw new CustomException(ErroEnums.APIERRO.getCode(),new Object[]{},ErroEnums.APIERRO.getInfo() + "根据反馈的业务报文转为目标格式["
                    + context.getOperationCode() + "]时出错.");
        }
        log.info("resp==>"+result);
        return result;
    }

    @Deprecated
    //新的接口的soapAction统一记录到inf_comm_client_gvar表中(例：FTTHAKeyRepair)
    private void setSoapAction(String operationCode, Call call){
        if(operationCode.equals("inas.getHlrInfo"))  //呼转用户状态查询
            call.setSOAPActionURI("http://tempuri.org/getHlrInfo");
    }
}
